package net.sinodata.smartframework.schedulejob.base;

import net.sinodata.smartframework.component.SpringContext;
import org.quartz.Job;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.web.client.RestTemplate;

/**
 * Description: 定时任务后台抽象父类----抽象为了将该类成为一个公共方法（isNeedwork）的类
 * 
 * @author: yinliangyun
 * @date: 2021-5-18
 */
public abstract class AbstractScheduleJob implements Job {
	
	private static final Logger logger = LoggerFactory.getLogger(AbstractScheduleJob.class);

	private static final String HEART_BEAT = "heartbeat";//

	private static final String HEART_BEAT_OK = "OK";

	public boolean isNeedWork() {
		return true;
	}
	/**
	 * 多机部署的情况下，是否需要工作
	 * 
	 * @return

	public boolean isNeedWork() {
		String serviceName = this.getClass().getName();
		logger.info("AbstractScheduleJob isNeedWork serviceName : {}", serviceName);
		if (logger.isDebugEnabled()) {
			logger.debug("AbstractScheduleJob isNeedWork serviceName : {}", serviceName);
		}
		
		String currentServer = "http://" + ParamConfigUtils.SERVER_IP + ":" + ParamConfigUtils.SERVER_PORT + "/" + ParamConfigUtils.SERVER_NAME + "/";

		Redisson redisson = SpringContext.getBean(Redisson.class);
		StringRedisTemplate stringRedisTemplate = SpringContext.getBean(StringRedisTemplate.class);

		// 获取服务与地址的映射关系
		String taskServer = stringRedisTemplate.opsForValue().get(serviceName);
		logger.info("AbstractScheduleJob isNeedWork serviceName : {}, currentServer : {}, taskServer : {}", serviceName, currentServer, taskServer);

		// 如果分布式缓存中间件中的taskServer(该定时任务目前正在那台服务器中执行的信息)和当前服务器的currentServer（当前服务器的信息）相同 说明改定时任务正在当前服务中出于运行状态
		if (taskServer != null && taskServer.equals(currentServer)) {
			logger.info("AbstractScheduleJob isNeedWork taskServer equals currentServer");
			return true;
		// 如果分布式缓存中间件中的taskServer(改定时任务目前正在那台服务器中执行的信息)值为空 说明多机部署场景下还没有定时任务初始化到分布式缓存中间件成功 这时需要将该定时任务的信息与服务器信息绑定
		} else if (taskServer == null || !isAliveURL(taskServer)) {// 服务地址为空或者地址无效
			String lockKey = "schedule_map";
			RLock redissonLock = redisson.getLock(lockKey);
			try {
				// 加锁（阻塞等待），默认过期时间是30秒
				redissonLock.lock();  // setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS);
				taskServer = stringRedisTemplate.opsForValue().get(serviceName);
				if (taskServer == null || !isAliveURL(taskServer)) {
					logger.info("AbstractScheduleJob isNeedWork serviceName : {}, currentServer : {}", serviceName, currentServer);
					stringRedisTemplate.opsForValue().set(serviceName, currentServer);
					return true;
				} else {
					return false;
				}
			} finally {
				// 解锁，如果业务执行完成，就不会继续续期，即使没有手动释放锁，在30秒过后，也会释放锁
				redissonLock.unlock();
			}
		} else {
			logger.info("AbstractScheduleJob isNeedWork taskServer is null or taskServer is dead");
			return false;
		}
	}*/

	/**
	 * 心跳检查：如果返回true表示服务正常，如果返回false表示服务异常
	 * @param url
	 * @return
	 */
	public static boolean isAliveURL(String url) {
		try {
			RestTemplate restTemplate = (RestTemplate) SpringContext.getBean("restTemplate");
			String urls = url + HEART_BEAT;
			logger.info("AbstractScheduleJob isAliveURL urls : {}", urls);
			String resultMessage = restTemplate.getForObject(urls, String.class);
			logger.info("AbstractScheduleJob isAliveURL resultMessage : {}", resultMessage);
			if (HEART_BEAT_OK.equals(resultMessage)) {
				return true;
			}
		} catch (Exception e) {
			logger.info("AbstractScheduleJob isAliveURL Exception url : {}", url + "_" + e.getMessage(), e);
		}
		return false;
	}
	
}
